package com.ruoyi.web.controller.face.socketServer;

import com.google.gson.Gson;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.tongban.facedetect.constant.CommandEnum;
import com.ruoyi.tongban.facedetect.domain.MessageBody;
import com.ruoyi.tongban.facedetect.domain.WebSocketSessionBody;
import com.ruoyi.tongban.facedetect.utils.SessionCacheBody;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.MultiValueMap;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;

/**
 * @Description
 * @Author caiyanshan
 * @Date 2021/4/13 13:44
 * @Param
 * @Return
 */
@ServerEndpoint(path = "/", port = "8686", maxFramePayloadLength = "655360")
public class FaceSocketApi {
  
  private Logger logger = LoggerFactory.getLogger(FaceSocketApi.class);
  
  @BeforeHandshake
  public void handshake(Session session, HttpHeaders headers, @RequestParam String req,
                        @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
    session.setSubprotocols("stomp");
    
  }
  
  /**
   * 连接成功后执行方法
   * @param session
   * @param headers
   * @param req
   * @param reqMap
   * @param arg
   * @param pathMap
   */
  @OnOpen
  public void onOpen(Session session, HttpHeaders headers, @RequestParam String req,
                     @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
    
  }
  
  /**
   * 链接断掉后执行方法
   * @param session
   * @throws IOException
   */
  @OnClose
  public void onClose(Session session) throws IOException {
    
    Collection<WebSocketSessionBody> webSocketSessionList = SessionCacheBody.getAllSession();
    for(WebSocketSessionBody webSocketSession : webSocketSessionList){
      if(session == webSocketSession.getSession()){
        SessionCacheBody.removeSession(webSocketSession.getSn());
        logger.info("LoginOut was successful, the sn is : " + webSocketSession.getSn());
      }
    }
  }
  
  @OnError
  public void onError(Session session, Throwable throwable) {
    throwable.printStackTrace();
  }
  
  /**
   * @Description 接收到客户端发来消息
   * @Author caiyanshan
   * @Date 2021/4/6 15:20
   * @Param [session, message]
   * @Return void
   */
  @OnMessage
  public void onMessage(Session session, String json) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
    Gson gson = new Gson();
    MessageBody message = gson.fromJson(json, MessageBody.class);
    String command = message.getCmd();//指令,做精准匹配用
    logger.info("request ["+ command +"] data is : " + json);
    String resultString = "";
    for(CommandEnum commandEnum : CommandEnum.values()){//遍历所有指令
      if(commandEnum.name().equals(command)){//匹配上了通过反射找到该方法
        Class clazz = MySocketService.class;
        if(command.equals(CommandEnum.declare.name())){//登录方法需要传session和其他方法不一致
          Method method = clazz.getMethod(command, String.class, Session.class);
          resultString = (String)method.invoke(clazz.newInstance(), json, session);
        }else {
          Method method = clazz.getMethod(command, String.class);
          resultString = (String)method.invoke(clazz.newInstance(), json);
        }
        break;
      }
    }
    logger.info("response ["+ command +"] data is : " + resultString);
    if(StringUtils.isBlank(resultString)){
      return;
    }
    session.sendText(resultString);
  }
  
  @OnBinary
  public void onBinary(Session session, byte[] bytes) {
    for (byte b : bytes) {
      System.out.println(b);
    }
    session.sendBinary(bytes);
  }
  
  @OnEvent
  public void onEvent(Session session, Object evt) {
    if (evt instanceof IdleStateEvent) {
      IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
      switch (idleStateEvent.state()) {
        case READER_IDLE:
          System.out.println("read idle");
          break;
        case WRITER_IDLE:
          System.out.println("write idle");
          break;
        case ALL_IDLE:
          System.out.println("all idle");
          break;
        default:
          break;
      }
    }
  }
}
